#include "Fingerprint-protocol.h"

FingerprintProtocol::FingerprintProtocol(const vector<uint8_t> &packet) : packet(packet)
{
}

FingerprintProtocol::FingerprintProtocol()
{
}

// 添加包头
void FingerprintProtocol::addPacketHead(const uint16_t head)
{
	// 高字节在前 低在后
	packet.push_back(head >> 8);
	packet.push_back(head & 0xff);
}

// 添加地址
void FingerprintProtocol::addPacketAddr(uint32_t addr)
{
	// head = 0xFFFFFFFF
	for (int i = 0; i < 4; i++)
	{
		// 存放最高字节
		// 传送时候高字节在前
		packet.push_back(addr >> 24);
		addr = addr << 8;
	}
}

// 添加包标识ID
void FingerprintProtocol::addPacketID(uint8_t pid)
{
	packet.push_back(pid);
}

// 添加包长度
void FingerprintProtocol::addPacketLen(uint16_t len)
{
	// 高字节在前 低在后
	packet.push_back(len >> 8);
	packet.push_back(len & 0xff);
}

// 添加包内容
void FingerprintProtocol::addPacketContent(uint8_t *data, uint32_t size)
{
	for (int i = 0; i < size; i++)
	{
		packet.push_back(data[i]);
	}
}

/**
 * 添加校验
 */
void FingerprintProtocol::addPacketSum(void)
{
	uint16_t sum = 0;
	for (int i = 6; i < packet.size(); i++)
	{
		sum += packet[i];
	}
	packet.push_back(sum >> 8);
	packet.push_back(sum & 0xff);
}

void FingerprintProtocol::showPacket(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	// 4个16进制显示 [0] 成员高字节 [1] 低字节
	printf("packet head : %04x\n", getPacketHead());
	printf("packet addr : %08x\n", getPacketAddr());
	printf("packet id   : %02x\n", getPacketID());
	printf("packet len  : %04x\n", getPacketDataLen() + 2);
	printf("packet data : ");
	uint16_t datalen = getPacketDataLen();
	uint8_t *data = getPacketData();
	for (int i = 0; i < datalen; i++)
	{
		printf("%02x ", data[i]);
	}
	printf("\n");
	printf("packet sum: %04x\n", getPacketSum());
}

uint16_t FingerprintProtocol::getPacketSum(void) const
{
	int packetSize = packet.size();
	return (packet[packetSize - 2] << 8 | packet[packetSize - 1]);
}

bool FingerprintProtocol::isPacketError(void)
{
	uint16_t calcSum = 0;
	for (int i = 6; i < packet.size() - 2; i++)
	{
		calcSum += packet[i];
	}

	uint16_t packetSum = getPacketSum();
	// printf("calcSum:0x%04x, packetSum:0x%04x\n", calcSum, packetSum);
	return calcSum == packetSum ? false : true;
}

vector<uint8_t> FingerprintProtocol::getPakcet(void) const
{
	return packet;
}

uint8_t *FingerprintProtocol::getPacketData(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return pkt->data;
}

uint16_t FingerprintProtocol::getPacketDataLen(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return (pkt->len[0] << 8 | pkt->len[1]) - 2;
}

uint8_t FingerprintProtocol::getPacketID(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return pkt->pid;
}

uint32_t FingerprintProtocol::getPacketAddr(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	uint32_t packetAddr =
		(pkt->addr[0] << 24) | (pkt->addr[1] << 16) | (pkt->addr[2] << 8) | (pkt->addr[3] << 0);
	return packetAddr;
}

uint16_t FingerprintProtocol::getPacketHead(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return (pkt->head[0] << 8 | pkt->head[1]);
}

// 创建捂手信号
FingerprintProtocol FingerprintProtocol::makeHandshakeProtocol(void)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x03);
	uint8_t data[] = {0x53};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

// 通过数据包生产协议
FingerprintProtocol FingerprintProtocol::fromProtocolPacket(const vector<uint8_t> &packet)
{
	return FingerprintProtocol(packet);
}

// 生成探测数据包
FingerprintProtocol FingerprintProtocol::makeDetectImageProtocol(void)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x03);
	uint8_t data[] = {0x01};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

FingerprintProtocol FingerprintProtocol::makeImageFeatureProtocol(uint8_t bufferID)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x04);
	uint8_t data[] = {0x02, bufferID};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

// 特征合成模板
FingerprintProtocol FingerprintProtocol::makeImageTemplateProtocol(void)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x03);
	uint8_t data[] = {0x05};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

FingerprintProtocol FingerprintProtocol::makeStoreTemplateProtocol(uint16_t pos)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x06);
	uint8_t data[] = {0x06, 0x01, (uint8_t)(pos >> 8), (uint8_t)(pos & 0xff)};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

// 指纹比对 startPos起始位置，n 搜索个数
FingerprintProtocol FingerprintProtocol::makeSearchFingerPrintProtocol(uint16_t startPos, uint16_t n)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x08);
	uint8_t data[] = {0x04, 0x01,
					  (uint8_t)(startPos >> 8),
					  (uint8_t)(startPos & 0xff),
					  (uint8_t)(n >> 8),
					  (uint8_t)(n & 0xff)};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

// 删除指定指纹
FingerprintProtocol FingerprintProtocol::makeDeleteFingerPrintProtocol(uint16_t pos)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x07);
	uint8_t data[] = {
		0x0c,									   // 指令码
		0x00, 0x01,								   // 模版号
		(uint8_t)(pos >> 8), (uint8_t)(pos & 0xff) // 删除个数
	};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}

FingerprintProtocol FingerprintProtocol::makeClearFingerPrintProtocol(void)
{
	FingerprintProtocol protocol;
	protocol.addPacketHead();
	protocol.addPacketAddr();
	protocol.addPacketID(COMMAND_PACKET);
	protocol.addPacketLen(0x03);
	uint8_t data[] = {0x0d};
	protocol.addPacketContent(data, sizeof(data));
	protocol.addPacketSum();
	return protocol;
}
